package aliyun

import (
	"context"
	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/sts"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/google/uuid"
)

// Sts 公用操作句柄
var Sts = &sts2{
	accessKeyId:     g.Config().MustGet(context.Background(), "app.aliyun.accessId").String(),
	accessKeySecret: g.Config().MustGet(context.Background(), "app.aliyun.accessKey").String(),
	RoleArn:         g.Config().MustGet(context.Background(), "app.aliyun.sts.roleArn").String(),
	RegionId:        g.Config().MustGet(context.Background(), "app.aliyun.sts.regionId").String(),
	Endpoint:        g.Config().MustGet(context.Background(), "app.aliyun.sts.endpoint").String(),
	Expires:         g.Config().MustGet(context.Background(), "app.aliyun.sts.expires", 3600).Int(),
}

// sts2 sts重名 遵从oss命名方式
type sts2 struct {
	accessKeyId     string
	accessKeySecret string
	RoleArn         string
	RegionId        string `json:"-"`
	Endpoint        string `json:"-"`
	Expires         int
}

// stsPolicy policy模板
type stsPolicy struct {
	Version   string               `json:"Version"`
	Statement []stsPolicyStatement `json:"Statement"`
}

// stsPolicyStatement sts 策略描述
type stsPolicyStatement struct {
	Effect   string   `json:"Effect"`
	Action   []string `json:"Action"`
	Resource []string `json:"Resource"`
}

// stsCredential STS临时凭证
type stsCredential struct {
	AccessKeySecret string `json:"access_key_secret"`
	Expiration      int    `json:"expiration"`
	AccessKeyId     string `json:"access_key_id"`
	SecurityToken   string `json:"security_token"`
}

// ###############################################################
// OSS 授权参考 https://help.aliyun.com/document_detail/100680.html

var StsPolicyAction = stsPolicyAction{}

type stsPolicyAction struct {
}

func (s stsPolicyAction) OssPutObject() []string {
	return []string{"oss:PutObject"}
}
func (s stsPolicyAction) OssGetObject() []string {
	return []string{"oss:GetObject"}
}
func (s stsPolicyAction) OssDeleteObject() []string {
	return []string{"oss:DeleteObject"}
}
func (s stsPolicyAction) OssCopyObject() []string {
	return []string{"oss:GetObject", "oss:PutObject"}
}

// ###############################################################

// NewPolicy 生成策略
func (s *sts2) NewPolicy(resources []string, actions []string) *stsPolicy {
	policyStatements := []stsPolicyStatement{{
		Effect:   "Allow",
		Action:   actions,
		Resource: resources,
	}}

	return &stsPolicy{
		Version:   "1",
		Statement: policyStatements,
	}
}

// GetCredential 获取临时访问凭证
func (s *sts2) GetCredential(policy *stsPolicy) (*stsCredential, error) {

	//构建一个阿里云客户端, 用于发起请求。
	client, err := sts.NewClientWithAccessKey(s.RegionId, s.accessKeyId, s.accessKeySecret)
	//构建请求对象。
	request := sts.CreateAssumeRoleRequest()
	request.RoleArn = s.RoleArn
	request.RoleSessionName = uuid.New().String()
	request.DurationSeconds = requests.NewInteger(s.Expires)
	request.Policy = gconv.String(policy)
	request.Scheme = "https"
	//发起请求，并得到响应。
	response, err := client.AssumeRole(request)
	if err != nil {
		return nil, err
	}
	credential := &stsCredential{
		SecurityToken:   response.Credentials.SecurityToken,
		AccessKeyId:     response.Credentials.AccessKeyId,
		AccessKeySecret: response.Credentials.AccessKeySecret,
		Expiration:      s.Expires,
	}
	return credential, nil
}
